﻿using System;
using System.Collections;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace JY.Common.Tools
{
    /// <summary>
    /// Rsa加密
    /// </summary>
    public static class RsaEncrypt
    {
        #region # 获取公钥/私钥——KeyModel GetKeyPair()
        /// <summary>
        /// 获取公钥/私钥
        /// 每次生成的公钥和私钥都不一样
        /// </summary>
        /// <remarks>
        ///  Item1 公钥  Item2私钥
        /// </remarks>
        public static Tuple<string,string> GetKeyPair()
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();

            //包括专用参数： 如果为true，则包含公钥和私钥RSA密钥；false，仅包括公众钥匙 
            string publicKey = rsaCryptoServiceProvider.ToXmlString(false); //生成的是公开的解密key
            string privateKey = rsaCryptoServiceProvider.ToXmlString(true); //生成的是私有的既可以加密也可以解密的key
            return new Tuple<string, string>(publicKey, privateKey);
        }
        #endregion

        #region # RSA文件加密——void EncryptFile(string sourceFilePath, string targetFilePath, string encryptKey)
        /// <summary>
        /// RSA文件加密
        /// </summary>
        /// <param name="sourceFilePath">源文件路径</param>
        /// <param name="targetFilePath">目标文件路径</param>
        /// <param name="encryptKey">秘钥</param>
        public static void EncryptFile(string sourceFilePath, string targetFilePath, string encryptKey)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            //导入密钥
            rsaCryptoServiceProvider.FromXmlString(encryptKey);

            using (FileStream sourceFileStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read))
            {
                using (FileStream targetFileStream = new FileStream(targetFilePath, FileMode.Create))
                {
                    targetFileStream.Seek(0, SeekOrigin.Begin);

                    int bufferSize = rsaCryptoServiceProvider.KeySize / 12;
                    byte[] data = new byte[bufferSize];
                    while (sourceFileStream.Read(data, 0, bufferSize) != 0)
                    {
                        //加密
                        byte[] result = rsaCryptoServiceProvider.Encrypt(data, true);
                        targetFileStream.Write(result, 0, result.Length);
                    }
                }
            }
        }
        #endregion

        #region # RSA文件解密——void DecryptFile(string sourceFilePath, string targetFilePath, string encryptKey)
        /// <summary>
        /// RSA文件解密
        /// </summary>
        /// <param name="sourceFilePath">源文件路径</param>
        /// <param name="targetFilePath">目标文件路径</param>
        /// <param name="encryptKey">秘钥</param>
        public static void DecryptFile(string sourceFilePath, string targetFilePath, string encryptKey)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            //导入密钥
            rsaCryptoServiceProvider.FromXmlString(encryptKey);

            using (FileStream sourceFileStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read))
            {
                using (FileStream targetFileStream = new FileStream(targetFilePath, FileMode.Create, FileAccess.Write))
                {
                    byte[] data = new byte[128];
                    targetFileStream.Seek(0, SeekOrigin.Begin);
                    while (sourceFileStream.Read(data, 0, 128) != 0)
                    {
                        //解密
                        byte[] result = rsaCryptoServiceProvider.Decrypt(data, true);
                        targetFileStream.Write(result, 0, result.Length);
                    }
                }
            }
        }
        #endregion

        #region # RSA字符加密——string Encrypt(string content, string encryptKey)
        /// <summary>
        /// RSA字符加密
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="encryptKey">秘钥</param>
        /// <returns>加密字符</returns>
        public static string Encrypt(string content, string encryptKey)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            rsaCryptoServiceProvider.FromXmlString(encryptKey);
            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            byte[] dataToEncrypt = unicodeEncoding.GetBytes(content);
            byte[] resultBytes = rsaCryptoServiceProvider.Encrypt(dataToEncrypt, false);
            return Convert.ToBase64String(resultBytes);
        }
        #endregion

        #region # 生成公钥私钥，同时完成字符加密——string Encrypt(string content, out string publicKey, out string privateKey)
        /// <summary>
        /// 生成公钥私钥，同时完成字符加密
        /// </summary>
        /// <param name="content"></param>
        /// <param name="publicKey">加密key</param>
        /// <param name="privateKey">解密key</param>
        /// <returns>加密字符</returns>
        private static string Encrypt(string content, out string publicKey, out string privateKey)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            publicKey = rsaCryptoServiceProvider.ToXmlString(false);
            privateKey = rsaCryptoServiceProvider.ToXmlString(true);

            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            byte[] dataToEncrypt = unicodeEncoding.GetBytes(content);
            byte[] resultBytes = rsaCryptoServiceProvider.Encrypt(dataToEncrypt, false);
            return Convert.ToBase64String(resultBytes);
        }
        #endregion

        #region # RSA字符解密——string Decrypt(string content, string decryptKey)
        /// <summary>
        /// RSA字符解密
        /// </summary>
        /// <param name="content">加密字符</param>
        /// <param name="decryptKey">秘钥</param>
        /// <returns>解密字符</returns>
        public static string Decrypt(string content, string decryptKey)
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            rsaCryptoServiceProvider.FromXmlString(decryptKey);

            byte[] dataToDecrypt = Convert.FromBase64String(content);
            byte[] resultBytes = rsaCryptoServiceProvider.Decrypt(dataToDecrypt, false);
            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            return unicodeEncoding.GetString(resultBytes);
        }
        #endregion

        #region # 生成签名——string SignData(string content, string privatekey)
        /// <summary>
        /// 生成签名
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="privatekey">私钥</param>
        /// <returns></returns>
        public static string SignData(string content, string privatekey)
        {
            byte[] messagebytes = Encoding.UTF8.GetBytes(content);
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            rsaCryptoServiceProvider.FromXmlString(privatekey);
            byte[] signData = rsaCryptoServiceProvider.SignData(messagebytes, "SHA1");
            return Convert.ToBase64String(signData);
        }
        #endregion

        #region # 验证签名——bool VerifyData(string content, string autograph, string publickey)
        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="content">原文</param>
        /// <param name="autograph">签名</param>
        /// <param name="publickey">共有key</param>
        /// <returns></returns>
        public static bool VerifyData(string content, string autograph, string publickey)
        {
            byte[] messagebytes = Encoding.UTF8.GetBytes(content);
            byte[] messageAutographbytes = Convert.FromBase64String(autograph);
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            rsaCryptoServiceProvider.FromXmlString(publickey);
            bool bVerify = rsaCryptoServiceProvider.VerifyData(messagebytes, "SHA1", messageAutographbytes);
            return bVerify;
        }
        #endregion
    }
}
